package cn.fuxi2022.module.info.service.impl;

import cn.fuxi2022.core.exception.SmartGroupException;
import cn.fuxi2022.core.utils.ExecutortUtils;
import cn.fuxi2022.model.empty.applets.GroupStudentInfo;
import cn.fuxi2022.model.empty.count.DoughnutChart;
import cn.fuxi2022.module.info.mapper.GroupStudentInfoMapper;
import cn.fuxi2022.module.info.service.GroupStudentInfoCountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Supplier;

@Slf4j
@Service
public class GroupStudentInfoCountServiceImpl implements GroupStudentInfoCountService {

    @Autowired
    private GroupStudentInfoMapper groupStudentInfoMapper;


    @Override
    // 使用redis缓存，确保 value 和 key 在IDEA正确识别，显示为绿色！！
    @Cacheable(value = "SmartGroup:info", key = "'groupStudentInfoCount'")
    public Map groupStudentInfoCount() {

        long l1 = System.currentTimeMillis();

        // 创建线程池
        ThreadPoolExecutor threadPool = ExecutortUtils.getThreadPool();
        threadPool.submit(() -> {
        });

        // 线程1
        CompletableFuture<List<DoughnutChart>> future1 = CompletableFuture.supplyAsync(new Supplier<List<DoughnutChart>>() {
            @Override
            public List<DoughnutChart> get() {
                return countSexToMap();
            }
        }, ExecutortUtils.getThreadPool());

        // 线程2
        CompletableFuture<List<DoughnutChart>> future2 = CompletableFuture.supplyAsync(new Supplier<List<DoughnutChart>>() {
            @Override
            public List<DoughnutChart> get() {
                return countCollegeToMap();
            }
        }, ExecutortUtils.getThreadPool());

        // 线程3
        CompletableFuture<List<DoughnutChart>> future3 = CompletableFuture.supplyAsync(new Supplier<List<DoughnutChart>>() {
            @Override
            public List<DoughnutChart> get() {
                return getStudentInfoCount();
            }
        }, ExecutortUtils.getThreadPool());

        CompletableFuture<List<DoughnutChart>> future4 = CompletableFuture.supplyAsync(new Supplier<List<DoughnutChart>>() {
            @Override
            public List<DoughnutChart> get() {
                return getDegreeToMap();
            }
        }, ExecutortUtils.getThreadPool());
        CompletableFuture<List<DoughnutChart>> future5 = CompletableFuture.supplyAsync(new Supplier<List<DoughnutChart>>() {
            @Override
            public List<DoughnutChart> get() {
                return getDirectionToMap();
            }
        }, ExecutortUtils.getThreadPool());

        // 线程4
        CompletableFuture<List<DoughnutChart>> future6 = CompletableFuture.supplyAsync(new Supplier<List<DoughnutChart>>() {
            @Override
            public List<DoughnutChart> get() {
                return groupStudentInfoMapper.getStudentGradeCount();
            }
        }, ExecutortUtils.getThreadPool());

        // 线程5
        CompletableFuture<Integer> future7 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                return groupStudentInfoMapper.getStudentCount();
            }
        }, ExecutortUtils.getThreadPool());

        // 线程8
        CompletableFuture<Integer> future8 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                return groupStudentInfoMapper.getIsStudentCount();
            }
        }, ExecutortUtils.getThreadPool());

        // 线程9
        CompletableFuture<List<DoughnutChart>> future9 = CompletableFuture.supplyAsync(new Supplier<List<DoughnutChart>>() {
            @Override
            public List<DoughnutChart> get() {
                return groupStudentInfoMapper.getdormToMap();
            }
        }, ExecutortUtils.getThreadPool());

        // 线程10
        CompletableFuture<List<GroupStudentInfo>> future10 = CompletableFuture.supplyAsync(new Supplier<List<GroupStudentInfo>>() {
            @Override
            public List<GroupStudentInfo> get() {
                return groupStudentInfoMapper.getStudentListForBigData();
            }
        }, ExecutortUtils.getThreadPool());


        // 下面要做封装了，在做封装之前必须要等砂上面的三个任务查询完了
        //get是个阻塞方法， 三个任务都返回后get才可以解除阻塞
        try {
            CompletableFuture.allOf(future1, future2, future3, future4, future5, future6, future7, future8, future9, future10).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            throw new SmartGroupException("多线程统计数据失败");
        }

        long l2 = System.currentTimeMillis();

        log.info("groupStudentInfoCount统计耗时时间{}", l2 - l1);

        HashMap<String, Object> data = new HashMap<>();
        try {
            data.put("sex", future1.get());
            data.put("college", future2.get());
            data.put("studentInfoCount", future3.get());
            data.put("degree", future4.get());
            data.put("direction", future5.get());
            data.put("studentGradeCount", future6.get());
            data.put("studentCount", future7.get());
            data.put("isStudentCount", future8.get());
            data.put("dormCount", future9.get());
            data.put("studentListForBigData", future10.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            throw new SmartGroupException("多线程统计获取数据失败");
        }

        return data;
    }

    @Override
    @CacheEvict(value = "SmartGroup:info", key = "'groupStudentInfoCount'")
    public void groupStudentInfoRefresh() {
        log.info("groupStudentInfoCount缓存已经清空");
    }

    public List<DoughnutChart> countSexToMap() {
        List<DoughnutChart> mapList = groupStudentInfoMapper.countSexToMap();

        mapList.forEach(doughnutChart -> {
            if (!ObjectUtils.isEmpty(doughnutChart.getName())) {
                switch (doughnutChart.getName()) {
                    case "0":
                        doughnutChart.setName("未知");
                        break;
                    case "1":
                        doughnutChart.setName("女");
                        break;
                    case "2":
                        doughnutChart.setName("男");
                        break;
                    default:
                        break;
                }
            }
        });

        return mapList;
    }

    public List<DoughnutChart> countCollegeToMap() {
        List<DoughnutChart> mapList = groupStudentInfoMapper.countCollegeToMap();

        mapList.forEach(doughnutChart -> {
            if (!ObjectUtils.isEmpty(doughnutChart.getName())) {
                switch (doughnutChart.getName()) {
                    case "0":
                        doughnutChart.setName("其他");
                        break;
                    case "1":
                        doughnutChart.setName("信息技术学院");
                        break;
                    case "2":
                        doughnutChart.setName("电气与电子工程学院");
                        break;
                    case "3":
                        doughnutChart.setName("艺术系");
                        break;
                    case "4":
                        doughnutChart.setName("体育系");
                        break;
                    case "5":
                        doughnutChart.setName("经济管理学院");
                        break;
                    case "6":
                        doughnutChart.setName("建设学院");
                        break;
                    case "7":
                        doughnutChart.setName("外国语学院");
                        break;
                    case "8":
                        doughnutChart.setName("智能制造学院");
                        break;
                    case "9":
                        doughnutChart.setName("会计学院");
                        break;
                    default:
                        break;
                }
            }
        });

        return mapList;
    }

    public List<DoughnutChart> getStudentInfoCount() {
        DoughnutChart[] charts = new DoughnutChart[]{
                new DoughnutChart("登录未完善，等待登录授权", 0),
                new DoughnutChart("登录已完成，等待开始入社", 0),
                new DoughnutChart("未支付社费", 0),
                new DoughnutChart("未添加群聊", 0),
                new DoughnutChart("入社成功", 0)};

        List<Map<String, Object>> studentInfoCount = groupStudentInfoMapper.getStudentInfoCount();

        studentInfoCount.forEach(stringObjectMap -> {
            if (!ObjectUtils.isEmpty(stringObjectMap.get("is_student"))) {
                Double isStudent = (Double) stringObjectMap.get("is_student");

                if (isStudent == 1) {
                    if (ObjectUtils.isEmpty(stringObjectMap.get("nickname"))) {
                        charts[0].setValue(charts[0].getValue() + 1);
                    } else {
                        charts[1].setValue(charts[1].getValue() + 1);
                    }
                } else if (isStudent == 2) {
                    charts[2].setValue(charts[2].getValue() + 1);
                } else if (isStudent == 3) {
                    charts[3].setValue(charts[3].getValue() + 1);
                } else if (isStudent == 4) {
                    charts[4].setValue(charts[4].getValue() + 1);
                }
            }
        });

        return Arrays.asList(charts);
    }

    public List<DoughnutChart> getDegreeToMap() {
        List<DoughnutChart> mapList = groupStudentInfoMapper.getDegreeToMap();

        mapList.forEach(doughnutChart -> {
            if (!ObjectUtils.isEmpty(doughnutChart.getName())) {
                switch (doughnutChart.getName()) {
                    case "0":
                        doughnutChart.setName("未确定");
                        break;
                    case "1":
                        doughnutChart.setName("小白");
                        break;
                    case "2":
                        doughnutChart.setName("菜鸟");
                        break;
                    case "3":
                        doughnutChart.setName("老鸟");
                        break;
                    default:
                        break;
                }
            }
        });

        return mapList;
    }

    public List<DoughnutChart> getDirectionToMap() {
        List<DoughnutChart> mapList = groupStudentInfoMapper.getDirectionToMap();

        mapList.forEach(doughnutChart -> {
            if (!ObjectUtils.isEmpty(doughnutChart.getName())) {
                switch (doughnutChart.getName()) {
                    case "0":
                        doughnutChart.setName("未确定");
                        break;
                    case "1":
                        doughnutChart.setName("嵌入式");
                        break;
                    case "2":
                        doughnutChart.setName("前端");
                        break;
                    case "3":
                        doughnutChart.setName("后端");
                        break;
                    default:
                        break;
                }
            }
        });

        return mapList;
    }
}
